package com.ml.mall.api.sys;


import com.ml.mall.annotations.OperLog;
import com.ml.mall.api.BaseController;
import com.ml.mall.bean.base.ApiRestResult;
import com.ml.mall.bean.req.sys.*;
import com.ml.mall.bean.res.sys.UserQueryInfoRes;
import com.ml.mall.bean.vo.sys.LoginUserVO;
import com.ml.mall.consts.CommonConsts;
import com.ml.mall.consts.PermissionConst;
import com.ml.mall.consts.UserConsts;
import com.ml.mall.entity.log.OperationLog;
import com.ml.mall.entity.sys.SysUser;
import com.ml.mall.enums.RetStatusNum;
import com.ml.mall.security.JwtUtil;
import com.ml.mall.service.log.OperationLogService;
import com.ml.mall.service.sys.ISysRoleUserService;
import com.ml.mall.service.sys.SysUserService;
import com.ml.mall.utils.HttpUtil;
import com.ml.mall.utils.MD5;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Date;

/**
 * <p>
 * 用户账号
 * </p>
 *
 * @author kyyang
 * Created 2021-01-05
 */

@RestController
@RequestMapping("/user")
@Slf4j
@Api(tags = "【auth】账户")
public class SysUserController extends BaseController {


    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ISysRoleUserService iSysRoleUserService;

    @Autowired
    private OperationLogService operationLogService;

    @Value("${mall.ml.version}")
    private String operVer;

    /**
     * @description: 用户登录
     * 登录时候无token 不能通过切点去用户信息
     * @author kyyang
     * @date 2021/1/6 19:18
     * @version 1.0
     */
    @RequestMapping(method = RequestMethod.POST, path = "/login")
    @ApiOperation("用户登录")
////  @RequiresPermissions(PermissionConst.USER_LOGIN) //放行，不启用
    public ApiRestResult login(@Valid @RequestBody SysLoginParam loginParam) {
        try {

            String userName = loginParam.getAcc();
            String password = loginParam.getPwd();

            SysUser user = sysUserService.findByAccount(userName);
            if (user == null){
                return ApiRestResult.err(RetStatusNum.ACC_NO.getMessage(), RetStatusNum.ACC_NO.getCode());
            }
            //账号0正常1禁用
            if (user.getState().equals(UserConsts.ABNORMAL_STATE)) {
                return ApiRestResult.err(RetStatusNum.ACC_FREEZE.getMessage(), RetStatusNum.ACC_FREEZE.getCode());
            }else
            if (user.getState().equals(UserConsts.DELETE_STATE)) {
                return ApiRestResult.err(RetStatusNum.ACC_DEL.getMessage(), RetStatusNum.ACC_DEL.getCode());
            }
            String passwdMd5 = MD5.md5(password, user.getSalt());

            if (!user.getPwd().equals(passwdMd5)) {
                return ApiRestResult.err(RetStatusNum.ACC_ERROR.getMessage(), RetStatusNum.ACC_ERROR.getCode());
            }
//            List<SysRoleUser> sysRoleUsers = iSysRoleUserService.listByUserId(user.getId());
//            if (sysRoleUsers == null || sysRoleUsers.size() < 1) {
//                return ApiRestResult.err(RetStatusNum.NO_PERMISSION.getMessage(), RetStatusNum.NO_PERMISSION.getCode());
//            }
            String token = sysUserService.loginForToken(user);
            LoginUserVO loginUserResponse = new LoginUserVO();
            loginUserResponse.setUserId(user.getId());
            loginUserResponse.setCompanyId(user.getCompanyId());
            loginUserResponse.setRoleType(user.getRoleType());
            loginUserResponse.setToken(token);

            //用户登录埋点
            OperationLog entiry = new OperationLog();
            entiry.setOperModule("sys");
            entiry.setOperDesc("用户登录");
            entiry.setOperIp(HttpUtil.getIp());
            entiry.setOperMethod("login");
            // entiry.setOperReqParam(JSON.toJSONString(loginParam));
            //entiry.setOperResParam(JSON.toJSONString(loginUserResponse));
            entiry.setOperUri("/sys/login");
            entiry.setOperType("login");
            entiry.setOperVer(operVer);
            entiry.setOperCreateTime(new Date());
            entiry.setOperUserId(user.getAcc());
            entiry.setOperUserName(user.getName());
            entiry.setRoleId(user.getRoleId());
            entiry.setRoleType(user.getRoleType());
            operationLogService.save(entiry);


            //记录登录时间
            SysUser u = new SysUser();
            u.setId(user.getId());
            u.setLastLoginAt(new Date());
            sysUserService.updateById(u);

            return ApiRestResult.ok(loginUserResponse);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return ApiRestResult.err("登录时失败");

    }

    @RequestMapping(method = RequestMethod.POST, path = "/logout")
    @OperLog(operDesc = "注销登录", operModul = "sys", operType = "logout")
    @ApiOperation("注销登录")
////  @RequiresPermissions(PermissionConst.USER_LOGOUT) //放行，不启用
    public ApiRestResult logout() {
        sysUserService.logout();
        return ApiRestResult.ok();
    }

    @RequestMapping(method = RequestMethod.POST, path = "/query/same_name")
    @OperLog(operDesc = "查询重名用户", operModul = "sys", operType = "querySameName")
    @ApiOperation("查询重名用户")
//  @RequiresPermissions(PermissionConst.USER_QUERY_SAME_NAME) //未发现调用
    public ApiRestResult queryByName(@RequestBody @Valid SysQuerySameNameDto sysQuerySameNameDto) {
        return ApiRestResult.ok(sysUserService.queryByName(sysQuerySameNameDto));
    }


    @RequestMapping(method = RequestMethod.POST, path = "/forgetPasswdEmail")
////  @RequiresPermissions(PermissionConst.USER_FORGET_PASSWD_EMAIL) //放行，不启用
    public ApiRestResult forgetPasswd2Email(@RequestBody @Valid SysUserForgetPasswdEmail sysUserForgetPasswdEmail) {
        sysUserService.forgetPasswd2Email(sysUserForgetPasswdEmail);
        return ApiRestResult.ok();
    }


    @RequestMapping(method = RequestMethod.POST, path = "/forgetPasswd")
////  @RequiresPermissions(PermissionConst.USER_FORGET_PASSWD) //放行，不启用
    public ApiRestResult forgetPasswd(@RequestBody @Valid SysUserForgetPasswdDto dto) {
        //用户忘记密码操作记录
        OperationLog entiry = new OperationLog();
        entiry.setOperModule("sys");
        entiry.setOperDesc("forgetPasswd");
        entiry.setOperIp(HttpUtil.getIp());
        entiry.setOperMethod("forgetPasswd");
        entiry.setOperUri("/sys/forgetPasswd");
        entiry.setOperType("forgetPasswd");
        entiry.setOperVer(operVer);
        entiry.setOperCreateTime(new Date());
        entiry.setOperUserId(dto.getAcc());
        entiry.setOperUserName("forget");
        operationLogService.save(entiry);

        return sysUserService.forgetPasswd(dto);
    }


    @PostMapping("/query_one")
    @ApiOperation("账户登录后，返回用户信息")
//  @RequiresPermissions(PermissionConst.USER_QUERY_ONE)
    public ApiRestResult sysUserQueryInfo(@RequestBody @Valid SysUserQueryOneDto dto){
        UserQueryInfoRes resUser = sysUserService.queryOneSysUser(dto);
        return ApiRestResult.ok(resUser);
    }


    @PostMapping("/query_page")
    @ApiOperation("账户分页查询")
//  @RequiresPermissions(PermissionConst.USER_QUERY_PAGE)
    public ApiRestResult accountQuery(@RequestBody @Valid SysUserQueryDto dto) {
        return ApiRestResult.ok(sysUserService.selectSelfCompanyAccByPage(dto));
    }

    @RequestMapping(method = RequestMethod.POST, path = "/new")
    @OperLog(operDesc = "AccountNew", operModul = "Account", operType = "New")
    @ApiOperation("账户创建")
//  @RequiresPermissions(PermissionConst.USER_NEW)
    public ApiRestResult accountNew(@Valid @RequestBody SysUserDto accUserDto) {
        //检查该用户是否存在
        SysUser byAccount = sysUserService.findByAccount(accUserDto.getAcc());
        if (byAccount != null) {
            return ApiRestResult.err(RetStatusNum.ACC_REP.getMessage(), RetStatusNum.ACC_REP.getCode());
        }
        sysUserService.addNewUser(accUserDto);
        return ApiRestResult.ok();
    }

    @RequestMapping(method = RequestMethod.POST, path = "/edit/info")
    @OperLog(operDesc = "账户信息修改", operModul = "sys", operType = "edit")
    @ApiOperation("账户信息修改")
//  @RequiresPermissions(PermissionConst.USER_EDIT_INFO)
    public ApiRestResult editInfo(@Valid @RequestBody SysUserEditDto accUserEditDto) {
        SysUser byAccount = sysUserService.getById(accUserEditDto.getId());
        if (byAccount == null) {
            return ApiRestResult.err(RetStatusNum.ACC_NO.getMessage(), RetStatusNum.ACC_NO.getCode());
        }
//        //非管理员只能修改自己的信息：商户也可以禁用账号
        SysUser currentUser = getCurrentUser();
        if(!currentUser.getRoleType().equals(CommonConsts.ROLE_TYPE_ADMIN)){
            accUserEditDto.setCompanyId(currentUser.getCompanyId());
        }
        sysUserService.editInfo(accUserEditDto);
        return ApiRestResult.ok();
    }

    @RequestMapping(method = RequestMethod.POST, path = "/edit/resetpwd")
    @OperLog(operDesc = "账号重置密码", operModul = "sys", operType = "edit")
    @ApiOperation("账户重置密码")
//  @RequiresPermissions(PermissionConst.USER_EDIT_RESETPWD)//未发现调用
    public ApiRestResult editResetpwd(@Valid @RequestBody SysRepwdDto dto) {

        SysUser byAccount = sysUserService.getById(dto.getUserId());
        if (byAccount == null) {
            return ApiRestResult.err(RetStatusNum.ACC_NO.getMessage(), RetStatusNum.ACC_NO.getCode());
        }
        sysUserService.editResetpwd(byAccount);
        return ApiRestResult.ok();
    }

    @RequestMapping(method = RequestMethod.POST, path = "/edit/newpwd")
    @OperLog(operDesc = "登陆之后账号修改密码", operModul = "sys", operType = "edit")
    @ApiOperation("账号修改密码")
//  @RequiresPermissions(PermissionConst.USER_EDIT_NEWPWD)
    public ApiRestResult editPwd(@Valid @RequestBody SysUserEditPwdDto accUserEditPwdDto) {

        SysUser sysUser = sysUserService.getById(JwtUtil.getUserId());
        if (sysUser == null) {
            return ApiRestResult.err(RetStatusNum.ACC_NO.getMessage(), RetStatusNum.ACC_NO.getCode());
        }
        //校验旧密码是否正确
        String md5 = MD5.md5(accUserEditPwdDto.getOldpwd(), sysUser.getSalt());
        if(!sysUser.getPwd().equals(md5)){
            return ApiRestResult.err(RetStatusNum.ACC_OLD_PWD.getMessage(), RetStatusNum.ACC_OLD_PWD.getCode());
        }

        sysUserService.editPwd(sysUser,accUserEditPwdDto);
        return ApiRestResult.ok();
    }


    @RequestMapping(method = RequestMethod.POST, path = "/menu")
    @ApiOperation("当前账户菜单列表查询")
//  @RequiresPermissions(PermissionConst.USER_MENU)//未发现调用
    public ApiRestResult accountMenuQuery() {
        return ApiRestResult.ok(sysUserService.accountMenuQuery());
    }

    @RequestMapping(method = RequestMethod.POST, path = "/permissions")
    @ApiOperation("当前账户页面权限查询")
//  @RequiresPermissions(PermissionConst.USER_PERMISSIONS)//未发现调用
    public ApiRestResult accountPermissionsQuery(@RequestBody SysPermissionsDto accPermissionsDto) {
        return ApiRestResult.ok(sysUserService.accountPermissionsQuery(accPermissionsDto));
    }

    @RequestMapping(method = RequestMethod.POST, path = "/change/company")
    @ApiOperation("切换用户归属公司")
//  @RequiresPermissions(PermissionConst.USER_CHANGE_COMPANY)//未发现调用
    public ApiRestResult accountChangeCompany(@RequestBody SysUserChangeCompanyDto dto) {
        sysUserService.accountChangeCompany(dto);
        return ApiRestResult.ok();
    }

    @GetMapping("/reset/password")
    @ApiOperation("用户重置密码")
    public String resetPassword(@RequestParam("email") String email,@RequestParam("code") String code,@RequestParam("Paw") String password){
        boolean b = sysUserService.resetPassword(email, code,password);
        if(b){
            return "SUCCESS";
        }
        return "FAIL";
    }

}
